home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 9 Texturing / TexWaves / TexWavesApp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2016-03-02  |  36.4 KB  |  1,040 lines

  1. //***************************************************************************************
  2. // TexWavesApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "../../Common/d3dApp.h"
  6. #include "../../Common/MathHelper.h"
  7. #include "../../Common/UploadBuffer.h"
  8. #include "../../Common/GeometryGenerator.h"
  9. #include "FrameResource.h"
  10. #include "Waves.h"
  11.  
  12. using Microsoft::WRL::ComPtr;
  13. using namespace DirectX;
  14. using namespace DirectX::PackedVector;
  15.  
  16. #pragma comment(lib, "d3dcompiler.lib")
  17. #pragma comment(lib, "D3D12.lib")
  18.  
  19. const int gNumFrameResources = 3;
  20.  
  21. // Lightweight structure stores parameters to draw a shape.  This will
  22. // vary from app-to-app.
  23. struct RenderItem
  24. {
  25.     RenderItem() = default;
  26.  
  27.     // World matrix of the shape that describes the object's local space
  28.     // relative to the world space, which defines the position, orientation,
  29.     // and scale of the object in the world.
  30.     XMFLOAT4X4 World = MathHelper::Identity4x4();
  31.  
  32.     XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
  33.  
  34.     // Dirty flag indicating the object data has changed and we need to update the constant buffer.
  35.     // Because we have an object cbuffer for each FrameResource, we have to apply the
  36.     // update to each FrameResource.  Thus, when we modify obect data we should set 
  37.     // NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  38.     int NumFramesDirty = gNumFrameResources;
  39.  
  40.     // Index into GPU constant buffer corresponding to the ObjectCB for this render item.
  41.     UINT ObjCBIndex = -1;
  42.  
  43.     Material* Mat = nullptr;
  44.     MeshGeometry* Geo = nullptr;
  45.  
  46.     // Primitive topology.
  47.     D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  48.  
  49.     // DrawIndexedInstanced parameters.
  50.     UINT IndexCount = 0;
  51.     UINT StartIndexLocation = 0;
  52.     int BaseVertexLocation = 0;
  53. };
  54.  
  55. enum class RenderLayer : int
  56. {
  57.     Opaque = 0,
  58.     Count
  59. };
  60.  
  61. class TexWavesApp : public D3DApp
  62. {
  63. public:
  64.     TexWavesApp(HINSTANCE hInstance);
  65.     TexWavesApp(const TexWavesApp& rhs) = delete;
  66.     TexWavesApp& operator=(const TexWavesApp& rhs) = delete;
  67.     ~TexWavesApp();
  68.  
  69.     virtual bool Initialize()override;
  70.  
  71. private:
  72.     virtual void OnResize()override;
  73.     virtual void Update(const GameTimer& gt)override;
  74.     virtual void Draw(const GameTimer& gt)override;
  75.  
  76.     virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
  77.     virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
  78.     virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
  79.  
  80.     void OnKeyboardInput(const GameTimer& gt);
  81.     void UpdateCamera(const GameTimer& gt);
  82.     void AnimateMaterials(const GameTimer& gt);
  83.     void UpdateObjectCBs(const GameTimer& gt);
  84.     void UpdateMaterialCBs(const GameTimer& gt);
  85.     void UpdateMainPassCB(const GameTimer& gt);
  86.     void UpdateWaves(const GameTimer& gt); 
  87.  
  88.     void LoadTextures();
  89.     void BuildRootSignature();
  90.     void BuildDescriptorHeaps();
  91.     void BuildShadersAndInputLayout();
  92.     void BuildLandGeometry();
  93.     void BuildWavesGeometry();
  94.     void BuildBoxGeometry();
  95.     void BuildPSOs();
  96.     void BuildFrameResources();
  97.     void BuildMaterials();
  98.     void BuildRenderItems();
  99.     void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
  100.  
  101.     std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> GetStaticSamplers();
  102.  
  103.     float GetHillsHeight(float x, float z)const;
  104.     XMFLOAT3 GetHillsNormal(float x, float z)const;
  105.  
  106. private:
  107.  
  108.     std::vector<std::unique_ptr<FrameResource>> mFrameResources;
  109.     FrameResource* mCurrFrameResource = nullptr;
  110.     int mCurrFrameResourceIndex = 0;
  111.  
  112.     UINT mCbvSrvDescriptorSize = 0;
  113.  
  114.     ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
  115.  
  116.     ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
  117.  
  118.     std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
  119.     std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
  120.     std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
  121.     std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
  122.     std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
  123.  
  124.     std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
  125.  
  126.     RenderItem* mWavesRitem = nullptr;
  127.  
  128.     // List of all the render items.
  129.     std::vector<std::unique_ptr<RenderItem>> mAllRitems;
  130.  
  131.     // Render items divided by PSO.
  132.     std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
  133.  
  134.     std::unique_ptr<Waves> mWaves;
  135.  
  136.     PassConstants mMainPassCB;
  137.  
  138.     XMFLOAT3 mEyePos = { 0.0f, 0.0f, 0.0f };
  139.     XMFLOAT4X4 mView = MathHelper::Identity4x4();
  140.     XMFLOAT4X4 mProj = MathHelper::Identity4x4();
  141.  
  142.     float mTheta = 1.5f*XM_PI;
  143.     float mPhi = XM_PIDIV2 - 0.1f;
  144.     float mRadius = 50.0f;
  145.  
  146.     POINT mLastMousePos;
  147. };
  148.  
  149. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
  150.     PSTR cmdLine, int showCmd)
  151. {
  152.     // Enable run-time memory check for debug builds.
  153. #if defined(DEBUG) | defined(_DEBUG)
  154.     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  155. #endif
  156.  
  157.     try
  158.     {
  159.         TexWavesApp theApp(hInstance);
  160.         if(!theApp.Initialize())
  161.             return 0;
  162.  
  163.         return theApp.Run();
  164.     }
  165.     catch(DxException& e)
  166.     {
  167.         MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
  168.         return 0;
  169.     }
  170. }
  171.  
  172. TexWavesApp::TexWavesApp(HINSTANCE hInstance)
  173.     : D3DApp(hInstance)
  174. {
  175. }
  176.  
  177. TexWavesApp::~TexWavesApp()
  178. {
  179.     if(md3dDevice != nullptr)
  180.         FlushCommandQueue();
  181. }
  182.  
  183. bool TexWavesApp::Initialize()
  184. {
  185.     if(!D3DApp::Initialize())
  186.         return false;
  187.  
  188.     // Reset the command list to prep for initialization commands.
  189.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
  190.  
  191.     // Get the increment size of a descriptor in this heap type.  This is hardware specific, 
  192.     // so we have to query this information.
  193.     mCbvSrvDescriptorSize = md3dDevice->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
  194.  
  195.     mWaves = std::make_unique<Waves>(128, 128, 1.0f, 0.03f, 4.0f, 0.2f);
  196.  
  197.     LoadTextures();
  198.     BuildRootSignature();
  199.     BuildDescriptorHeaps();
  200.     BuildShadersAndInputLayout();
  201.     BuildLandGeometry();
  202.     BuildWavesGeometry();
  203.     BuildBoxGeometry();
  204.     BuildMaterials();
  205.     BuildRenderItems();
  206.     BuildFrameResources();
  207.     BuildPSOs();
  208.  
  209.     // Execute the initialization commands.
  210.     ThrowIfFailed(mCommandList->Close());
  211.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  212.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  213.  
  214.     // Wait until initialization is complete.
  215.     FlushCommandQueue();
  216.  
  217.     return true;
  218. }
  219.  
  220. void TexWavesApp::OnResize()
  221. {
  222.     D3DApp::OnResize();
  223.  
  224.     // The window resized, so update the aspect ratio and recompute the projection matrix.
  225.     XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  226.     XMStoreFloat4x4(&mProj, P);
  227. }
  228.  
  229. void TexWavesApp::Update(const GameTimer& gt)
  230. {
  231.     OnKeyboardInput(gt);
  232.     UpdateCamera(gt);
  233.  
  234.     // Cycle through the circular frame resource array.
  235.     mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  236.     mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  237.  
  238.     // Has the GPU finished processing the commands of the current frame resource?
  239.     // If not, wait until the GPU has completed commands up to this fence point.
  240.     if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  241.     {
  242.         HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  243.         ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  244.         WaitForSingleObject(eventHandle, INFINITE);
  245.         CloseHandle(eventHandle);
  246.     }
  247.  
  248.     AnimateMaterials(gt);
  249.     UpdateObjectCBs(gt);
  250.     UpdateMaterialCBs(gt);
  251.     UpdateMainPassCB(gt);
  252.     UpdateWaves(gt);
  253. }
  254.  
  255. void TexWavesApp::Draw(const GameTimer& gt)
  256. {
  257.     auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  258.  
  259.     // Reuse the memory associated with command recording.
  260.     // We can only reset when the associated command lists have finished execution on the GPU.
  261.     ThrowIfFailed(cmdListAlloc->Reset());
  262.  
  263.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  264.     // Reusing the command list reuses memory.
  265.     ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  266.  
  267.     mCommandList->RSSetViewports(1, &mScreenViewport);
  268.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  269.  
  270.     // Indicate a state transition on the resource usage.
  271.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  272.         D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  273.  
  274.     // Clear the back buffer and depth buffer.
  275.     mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
  276.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  277.  
  278.     // Specify the buffers we are going to render to.
  279.     mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  280.  
  281.     ID3D12DescriptorHeap* descriptorHeaps[] = { mSrvDescriptorHeap.Get() };
  282.     mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
  283.  
  284.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  285.  
  286.     auto passCB = mCurrFrameResource->PassCB->Resource();
  287.     mCommandList->SetGraphicsRootConstantBufferView(2, passCB->GetGPUVirtualAddress());
  288.  
  289.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  290.  
  291.     // Indicate a state transition on the resource usage.
  292.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  293.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  294.  
  295.     // Done recording commands.
  296.     ThrowIfFailed(mCommandList->Close());
  297.  
  298.     // Add the command list to the queue for execution.
  299.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  300.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  301.  
  302.     // Swap the back and front buffers
  303.     ThrowIfFailed(mSwapChain->Present(0, 0));
  304.     mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
  305.  
  306.     // Advance the fence value to mark commands up to this fence point.
  307.     mCurrFrameResource->Fence = ++mCurrentFence;
  308.  
  309.     // Add an instruction to the command queue to set a new fence point. 
  310.     // Because we are on the GPU timeline, the new fence point won't be 
  311.     // set until the GPU finishes processing all the commands prior to this Signal().
  312.     mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  313. }
  314.  
  315. void TexWavesApp::OnMouseDown(WPARAM btnState, int x, int y)
  316. {
  317.     mLastMousePos.x = x;
  318.     mLastMousePos.y = y;
  319.  
  320.     SetCapture(mhMainWnd);
  321. }
  322.  
  323. void TexWavesApp::OnMouseUp(WPARAM btnState, int x, int y)
  324. {
  325.     ReleaseCapture();
  326. }
  327.  
  328. void TexWavesApp::OnMouseMove(WPARAM btnState, int x, int y)
  329. {
  330.     if((btnState & MK_LBUTTON) != 0)
  331.     {
  332.         // Make each pixel correspond to a quarter of a degree.
  333.         float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
  334.         float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
  335.  
  336.         // Update angles based on input to orbit camera around box.
  337.         mTheta += dx;
  338.         mPhi += dy;
  339.  
  340.         // Restrict the angle mPhi.
  341.         mPhi = MathHelper::Clamp(mPhi, 0.1f, MathHelper::Pi - 0.1f);
  342.     }
  343.     else if((btnState & MK_RBUTTON) != 0)
  344.     {
  345.         // Make each pixel correspond to 0.2 unit in the scene.
  346.         float dx = 0.2f*static_cast<float>(x - mLastMousePos.x);
  347.         float dy = 0.2f*static_cast<float>(y - mLastMousePos.y);
  348.  
  349.         // Update the camera radius based on input.
  350.         mRadius += dx - dy;
  351.  
  352.         // Restrict the radius.
  353.         mRadius = MathHelper::Clamp(mRadius, 5.0f, 150.0f);
  354.     }
  355.  
  356.     mLastMousePos.x = x;
  357.     mLastMousePos.y = y;
  358. }
  359.  
  360. void TexWavesApp::OnKeyboardInput(const GameTimer& gt)
  361. {
  362. }
  363.  
  364. void TexWavesApp::UpdateCamera(const GameTimer& gt)
  365. {
  366.     // Convert Spherical to Cartesian coordinates.
  367.     mEyePos.x = mRadius*sinf(mPhi)*cosf(mTheta);
  368.     mEyePos.z = mRadius*sinf(mPhi)*sinf(mTheta);
  369.     mEyePos.y = mRadius*cosf(mPhi);
  370.  
  371.     // Build the view matrix.
  372.     XMVECTOR pos = XMVectorSet(mEyePos.x, mEyePos.y, mEyePos.z, 1.0f);
  373.     XMVECTOR target = XMVectorZero();
  374.     XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  375.  
  376.     XMMATRIX view = XMMatrixLookAtLH(pos, target, up);
  377.     XMStoreFloat4x4(&mView, view);
  378. }
  379.  
  380. void TexWavesApp::AnimateMaterials(const GameTimer& gt)
  381. {
  382.     // Scroll the water material texture coordinates.
  383.     auto waterMat = mMaterials["water"].get();
  384.  
  385.     float& tu = waterMat->MatTransform(3, 0);
  386.     float& tv = waterMat->MatTransform(3, 1);
  387.  
  388.     tu += 0.1f * gt.DeltaTime();
  389.     tv += 0.02f * gt.DeltaTime();
  390.  
  391.     if(tu >= 1.0f)
  392.         tu -= 1.0f;
  393.  
  394.     if(tv >= 1.0f)
  395.         tv -= 1.0f;
  396.  
  397.     waterMat->MatTransform(3, 0) = tu;
  398.     waterMat->MatTransform(3, 1) = tv;
  399.  
  400.     // Material has changed, so need to update cbuffer.
  401.     waterMat->NumFramesDirty = gNumFrameResources;
  402. }
  403.  
  404. void TexWavesApp::UpdateObjectCBs(const GameTimer& gt)
  405. {
  406.     auto currObjectCB = mCurrFrameResource->ObjectCB.get();
  407.     for(auto& e : mAllRitems)
  408.     {
  409.         // Only update the cbuffer data if the constants have changed.  
  410.         // This needs to be tracked per frame resource.
  411.         if(e->NumFramesDirty > 0)
  412.         {
  413.             XMMATRIX world = XMLoadFloat4x4(&e->World);
  414.             XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
  415.  
  416.             ObjectConstants objConstants;
  417.             XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
  418.             XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
  419.  
  420.             currObjectCB->CopyData(e->ObjCBIndex, objConstants);
  421.  
  422.             // Next FrameResource need to be updated too.
  423.             e->NumFramesDirty--;
  424.         }
  425.     }
  426. }
  427.  
  428. void TexWavesApp::UpdateMaterialCBs(const GameTimer& gt)
  429. {
  430.     auto currMaterialCB = mCurrFrameResource->MaterialCB.get();
  431.     for(auto& e : mMaterials)
  432.     {
  433.         // Only update the cbuffer data if the constants have changed.  If the cbuffer
  434.         // data changes, it needs to be updated for each FrameResource.
  435.         Material* mat = e.second.get();
  436.         if(mat->NumFramesDirty > 0)
  437.         {
  438.             XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
  439.  
  440.             MaterialConstants matConstants;
  441.             matConstants.DiffuseAlbedo = mat->DiffuseAlbedo;
  442.             matConstants.FresnelR0 = mat->FresnelR0;
  443.             matConstants.Roughness = mat->Roughness;
  444.             XMStoreFloat4x4(&matConstants.MatTransform, XMMatrixTranspose(matTransform));
  445.  
  446.             currMaterialCB->CopyData(mat->MatCBIndex, matConstants);
  447.  
  448.             // Next FrameResource need to be updated too.
  449.             mat->NumFramesDirty--;
  450.         }
  451.     }
  452. }
  453.  
  454. void TexWavesApp::UpdateMainPassCB(const GameTimer& gt)
  455. {
  456.     XMMATRIX view = XMLoadFloat4x4(&mView);
  457.     XMMATRIX proj = XMLoadFloat4x4(&mProj);
  458.  
  459.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  460.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  461.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  462.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  463.  
  464.     XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
  465.     XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
  466.     XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
  467.     XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
  468.     XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
  469.     XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  470.     mMainPassCB.EyePosW = mEyePos;
  471.     mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
  472.     mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
  473.     mMainPassCB.NearZ = 1.0f;
  474.     mMainPassCB.FarZ = 1000.0f;
  475.     mMainPassCB.TotalTime = gt.TotalTime();
  476.     mMainPassCB.DeltaTime = gt.DeltaTime();
  477.     mMainPassCB.AmbientLight = { 0.25f, 0.25f, 0.35f, 1.0f };
  478.     mMainPassCB.Lights[0].Direction = { 0.57735f, -0.57735f, 0.57735f };
  479.     mMainPassCB.Lights[0].Strength = { 0.9f, 0.9f, 0.9f };
  480.     mMainPassCB.Lights[1].Direction = { -0.57735f, -0.57735f, 0.57735f };
  481.     mMainPassCB.Lights[1].Strength = { 0.5f, 0.5f, 0.5f };
  482.     mMainPassCB.Lights[2].Direction = { 0.0f, -0.707f, -0.707f };
  483.     mMainPassCB.Lights[2].Strength = { 0.2f, 0.2f, 0.2f };
  484.  
  485.     auto currPassCB = mCurrFrameResource->PassCB.get();
  486.     currPassCB->CopyData(0, mMainPassCB);
  487. }
  488.  
  489. void TexWavesApp::UpdateWaves(const GameTimer& gt)
  490. {
  491.     // Every quarter second, generate a random wave.
  492.     static float t_base = 0.0f;
  493.     if((mTimer.TotalTime() - t_base) >= 0.25f)
  494.     {
  495.         t_base += 0.25f;
  496.  
  497.         int i = MathHelper::Rand(4, mWaves->RowCount() - 5);
  498.         int j = MathHelper::Rand(4, mWaves->ColumnCount() - 5);
  499.  
  500.         float r = MathHelper::RandF(0.2f, 0.5f);
  501.  
  502.         mWaves->Disturb(i, j, r);
  503.     }
  504.  
  505.     // Update the wave simulation.
  506.     mWaves->Update(gt.DeltaTime());
  507.  
  508.     // Update the wave vertex buffer with the new solution.
  509.     auto currWavesVB = mCurrFrameResource->WavesVB.get();
  510.     for(int i = 0; i < mWaves->VertexCount(); ++i)
  511.     {
  512.         Vertex v;
  513.  
  514.         v.Pos = mWaves->Position(i);
  515.         v.Normal = mWaves->Normal(i);
  516.         
  517.         // Derive tex-coords from position by 
  518.         // mapping [-w/2,w/2] --> [0,1]
  519.         v.TexC.x = 0.5f + v.Pos.x / mWaves->Width();
  520.         v.TexC.y = 0.5f - v.Pos.z / mWaves->Depth();
  521.  
  522.         currWavesVB->CopyData(i, v);
  523.     }
  524.  
  525.     // Set the dynamic VB of the wave renderitem to the current frame VB.
  526.     mWavesRitem->Geo->VertexBufferGPU = currWavesVB->Resource();
  527. }
  528.  
  529. void TexWavesApp::LoadTextures()
  530. {
  531.     auto grassTex = std::make_unique<Texture>();
  532.     grassTex->Name = "grassTex";
  533.     grassTex->Filename = L"../../Textures/grass.dds";
  534.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  535.         mCommandList.Get(), grassTex->Filename.c_str(),
  536.         grassTex->Resource, grassTex->UploadHeap));
  537.  
  538.     auto waterTex = std::make_unique<Texture>();
  539.     waterTex->Name = "waterTex";
  540.     waterTex->Filename = L"../../Textures/water1.dds";
  541.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  542.         mCommandList.Get(), waterTex->Filename.c_str(),
  543.         waterTex->Resource, waterTex->UploadHeap));
  544.  
  545.     auto fenceTex = std::make_unique<Texture>();
  546.     fenceTex->Name = "fenceTex";
  547.     fenceTex->Filename = L"../../Textures/WoodCrate01.dds";
  548.     ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  549.         mCommandList.Get(), fenceTex->Filename.c_str(),
  550.         fenceTex->Resource, fenceTex->UploadHeap));
  551.  
  552.     mTextures[grassTex->Name] = std::move(grassTex);
  553.     mTextures[waterTex->Name] = std::move(waterTex);
  554.     mTextures[fenceTex->Name] = std::move(fenceTex);
  555. }
  556.  
  557. void TexWavesApp::BuildRootSignature()
  558. {
  559.     CD3DX12_DESCRIPTOR_RANGE texTable;
  560.     texTable.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
  561.  
  562.     // Root parameter can be a table, root descriptor or root constants.
  563.     CD3DX12_ROOT_PARAMETER slotRootParameter[4];
  564.  
  565.     // Perfomance TIP: Order from most frequent to least frequent.
  566.     slotRootParameter[0].InitAsDescriptorTable(1, &texTable, D3D12_SHADER_VISIBILITY_PIXEL);
  567.     slotRootParameter[1].InitAsConstantBufferView(0);
  568.     slotRootParameter[2].InitAsConstantBufferView(1);
  569.     slotRootParameter[3].InitAsConstantBufferView(2);
  570.  
  571.     auto staticSamplers = GetStaticSamplers();
  572.  
  573.     // A root signature is an array of root parameters.
  574.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(4, slotRootParameter,
  575.         (UINT)staticSamplers.size(), staticSamplers.data(),
  576.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  577.  
  578.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  579.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  580.     ComPtr<ID3DBlob> errorBlob = nullptr;
  581.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  582.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  583.  
  584.     if(errorBlob != nullptr)
  585.     {
  586.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  587.     }
  588.     ThrowIfFailed(hr);
  589.  
  590.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  591.         0,
  592.         serializedRootSig->GetBufferPointer(),
  593.         serializedRootSig->GetBufferSize(),
  594.         IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  595. }
  596.  
  597. void TexWavesApp::BuildDescriptorHeaps()
  598. {
  599.     //
  600.     // Create the SRV heap.
  601.     //
  602.     D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
  603.     srvHeapDesc.NumDescriptors = 3;
  604.     srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  605.     srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  606.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvDescriptorHeap)));
  607.  
  608.     //
  609.     // Fill out the heap with actual descriptors.
  610.     //
  611.     CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  612.  
  613.     auto grassTex = mTextures["grassTex"]->Resource;
  614.     auto waterTex = mTextures["waterTex"]->Resource;
  615.     auto fenceTex = mTextures["fenceTex"]->Resource;
  616.  
  617.     D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  618.     srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  619.     srvDesc.Format = grassTex->GetDesc().Format;
  620.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  621.     srvDesc.Texture2D.MostDetailedMip = 0;
  622.     srvDesc.Texture2D.MipLevels = -1;
  623.     md3dDevice->CreateShaderResourceView(grassTex.Get(), &srvDesc, hDescriptor);
  624.  
  625.     // next descriptor
  626.     hDescriptor.Offset(1, mCbvSrvDescriptorSize);
  627.  
  628.     srvDesc.Format = waterTex->GetDesc().Format;
  629.     md3dDevice->CreateShaderResourceView(waterTex.Get(), &srvDesc, hDescriptor);
  630.  
  631.     // next descriptor
  632.     hDescriptor.Offset(1, mCbvSrvDescriptorSize);
  633.  
  634.     srvDesc.Format = fenceTex->GetDesc().Format;
  635.     md3dDevice->CreateShaderResourceView(fenceTex.Get(), &srvDesc, hDescriptor);
  636. }
  637.  
  638. void TexWavesApp::BuildShadersAndInputLayout()
  639. {
  640.     mShaders["standardVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "VS", "vs_5_0");
  641.     mShaders["opaquePS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "PS", "ps_5_0");
  642.     
  643.     mInputLayout =
  644.     {
  645.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  646.         { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  647.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  648.     };
  649. }
  650.  
  651. void TexWavesApp::BuildLandGeometry()
  652. {
  653.     GeometryGenerator geoGen;
  654.     GeometryGenerator::MeshData grid = geoGen.CreateGrid(160.0f, 160.0f, 50, 50);
  655.  
  656.     //
  657.     // Extract the vertex elements we are interested and apply the height function to
  658.     // each vertex.  In addition, color the vertices based on their height so we have
  659.     // sandy looking beaches, grassy low hills, and snow mountain peaks.
  660.     //
  661.  
  662.     std::vector<Vertex> vertices(grid.Vertices.size());
  663.     for(size_t i = 0; i < grid.Vertices.size(); ++i)
  664.     {
  665.         auto& p = grid.Vertices[i].Position;
  666.         vertices[i].Pos = p;
  667.         vertices[i].Pos.y = GetHillsHeight(p.x, p.z);
  668.         vertices[i].Normal = GetHillsNormal(p.x, p.z);
  669.         vertices[i].TexC = grid.Vertices[i].TexC;
  670.     }
  671.  
  672.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  673.  
  674.     std::vector<std::uint16_t> indices = grid.GetIndices16();
  675.     const UINT ibByteSize = (UINT)indices.size() * sizeof(std::uint16_t);
  676.  
  677.     auto geo = std::make_unique<MeshGeometry>();
  678.     geo->Name = "landGeo";
  679.  
  680.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  681.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  682.  
  683.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  684.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  685.  
  686.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  687.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  688.  
  689.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  690.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  691.  
  692.     geo->VertexByteStride = sizeof(Vertex);
  693.     geo->VertexBufferByteSize = vbByteSize;
  694.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  695.     geo->IndexBufferByteSize = ibByteSize;
  696.  
  697.     SubmeshGeometry submesh;
  698.     submesh.IndexCount = (UINT)indices.size();
  699.     submesh.StartIndexLocation = 0;
  700.     submesh.BaseVertexLocation = 0;
  701.  
  702.     geo->DrawArgs["grid"] = submesh;
  703.  
  704.     mGeometries["landGeo"] = std::move(geo);
  705. }
  706.  
  707. void TexWavesApp::BuildWavesGeometry()
  708. {
  709.     std::vector<std::uint16_t> indices(3 * mWaves->TriangleCount()); // 3 indices per face
  710.     assert(mWaves->VertexCount() < 0x0000ffff);
  711.  
  712.     // Iterate over each quad.
  713.     int m = mWaves->RowCount();
  714.     int n = mWaves->ColumnCount();
  715.     int k = 0;
  716.     for(int i = 0; i < m - 1; ++i)
  717.     {
  718.         for(int j = 0; j < n - 1; ++j)
  719.         {
  720.             indices[k] = i*n + j;
  721.             indices[k + 1] = i*n + j + 1;
  722.             indices[k + 2] = (i + 1)*n + j;
  723.  
  724.             indices[k + 3] = (i + 1)*n + j;
  725.             indices[k + 4] = i*n + j + 1;
  726.             indices[k + 5] = (i + 1)*n + j + 1;
  727.  
  728.             k += 6; // next quad
  729.         }
  730.     }
  731.  
  732.     UINT vbByteSize = mWaves->VertexCount()*sizeof(Vertex);
  733.     UINT ibByteSize = (UINT)indices.size()*sizeof(std::uint16_t);
  734.  
  735.     auto geo = std::make_unique<MeshGeometry>();
  736.     geo->Name = "waterGeo";
  737.  
  738.     // Set dynamically.
  739.     geo->VertexBufferCPU = nullptr;
  740.     geo->VertexBufferGPU = nullptr;
  741.  
  742.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  743.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  744.  
  745.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  746.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  747.  
  748.     geo->VertexByteStride = sizeof(Vertex);
  749.     geo->VertexBufferByteSize = vbByteSize;
  750.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  751.     geo->IndexBufferByteSize = ibByteSize;
  752.  
  753.     SubmeshGeometry submesh;
  754.     submesh.IndexCount = (UINT)indices.size();
  755.     submesh.StartIndexLocation = 0;
  756.     submesh.BaseVertexLocation = 0;
  757.  
  758.     geo->DrawArgs["grid"] = submesh;
  759.  
  760.     mGeometries["waterGeo"] = std::move(geo);
  761. }
  762.  
  763. void TexWavesApp::BuildBoxGeometry()
  764. {
  765.     GeometryGenerator geoGen;
  766.     GeometryGenerator::MeshData box = geoGen.CreateBox(8.0f, 8.0f, 8.0f, 3);
  767.  
  768.     std::vector<Vertex> vertices(box.Vertices.size());
  769.     for (size_t i = 0; i < box.Vertices.size(); ++i)
  770.     {
  771.         auto& p = box.Vertices[i].Position;
  772.         vertices[i].Pos = p;
  773.         vertices[i].Normal = box.Vertices[i].Normal;
  774.         vertices[i].TexC = box.Vertices[i].TexC;
  775.     }
  776.  
  777.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  778.  
  779.     std::vector<std::uint16_t> indices = box.GetIndices16();
  780.     const UINT ibByteSize = (UINT)indices.size() * sizeof(std::uint16_t);
  781.  
  782.     auto geo = std::make_unique<MeshGeometry>();
  783.     geo->Name = "boxGeo";
  784.  
  785.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  786.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  787.  
  788.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  789.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  790.  
  791.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  792.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  793.  
  794.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  795.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  796.  
  797.     geo->VertexByteStride = sizeof(Vertex);
  798.     geo->VertexBufferByteSize = vbByteSize;
  799.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  800.     geo->IndexBufferByteSize = ibByteSize;
  801.  
  802.     SubmeshGeometry submesh;
  803.     submesh.IndexCount = (UINT)indices.size();
  804.     submesh.StartIndexLocation = 0;
  805.     submesh.BaseVertexLocation = 0;
  806.  
  807.     geo->DrawArgs["box"] = submesh;
  808.  
  809.     mGeometries["boxGeo"] = std::move(geo);
  810. }
  811.  
  812. void TexWavesApp::BuildPSOs()
  813. {
  814.     D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
  815.  
  816.     //
  817.     // PSO for opaque objects.
  818.     //
  819.     ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
  820.     opaquePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
  821.     opaquePsoDesc.pRootSignature = mRootSignature.Get();
  822.     opaquePsoDesc.VS = 
  823.     { 
  824.         reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
  825.         mShaders["standardVS"]->GetBufferSize()
  826.     };
  827.     opaquePsoDesc.PS = 
  828.     { 
  829.         reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
  830.         mShaders["opaquePS"]->GetBufferSize()
  831.     };
  832.     opaquePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  833.     opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  834.     opaquePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  835.     opaquePsoDesc.SampleMask = UINT_MAX;
  836.     opaquePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  837.     opaquePsoDesc.NumRenderTargets = 1;
  838.     opaquePsoDesc.RTVFormats[0] = mBackBufferFormat;
  839.     opaquePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
  840.     opaquePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
  841.     opaquePsoDesc.DSVFormat = mDepthStencilFormat;
  842.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
  843. }
  844.  
  845. void TexWavesApp::BuildFrameResources()
  846. {
  847.     for(int i = 0; i < gNumFrameResources; ++i)
  848.     {
  849.         mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(),
  850.             1, (UINT)mAllRitems.size(), (UINT)mMaterials.size(), mWaves->VertexCount()));
  851.     }
  852. }
  853.  
  854. void TexWavesApp::BuildMaterials()
  855. {
  856.     auto grass = std::make_unique<Material>();
  857.     grass->Name = "grass";
  858.     grass->MatCBIndex = 0;
  859.     grass->DiffuseSrvHeapIndex = 0;
  860.     grass->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  861.     grass->FresnelR0 = XMFLOAT3(0.01f, 0.01f, 0.01f);
  862.     grass->Roughness = 0.125f;
  863.  
  864.     // This is not a good water material definition, but we do not have all the rendering
  865.     // tools we need (transparency, environment reflection), so we fake it for now.
  866.     auto water = std::make_unique<Material>();
  867.     water->Name = "water";
  868.     water->MatCBIndex = 1;
  869.     water->DiffuseSrvHeapIndex = 1;
  870.     water->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  871.     water->FresnelR0 = XMFLOAT3(0.2f, 0.2f, 0.2f);
  872.     water->Roughness = 0.0f;
  873.  
  874.     auto wirefence = std::make_unique<Material>();
  875.     wirefence->Name = "wirefence";
  876.     wirefence->MatCBIndex = 2;
  877.     wirefence->DiffuseSrvHeapIndex = 2;
  878.     wirefence->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  879.     wirefence->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  880.     wirefence->Roughness = 0.25f;
  881.  
  882.     mMaterials["grass"] = std::move(grass);
  883.     mMaterials["water"] = std::move(water);
  884.     mMaterials["wirefence"] = std::move(wirefence);
  885. }
  886.  
  887. void TexWavesApp::BuildRenderItems()
  888. {
  889.     auto wavesRitem = std::make_unique<RenderItem>();
  890.     wavesRitem->World = MathHelper::Identity4x4();
  891.     XMStoreFloat4x4(&wavesRitem->TexTransform, XMMatrixScaling(5.0f, 5.0f, 1.0f));
  892.     wavesRitem->ObjCBIndex = 0;
  893.     wavesRitem->Mat = mMaterials["water"].get();
  894.     wavesRitem->Geo = mGeometries["waterGeo"].get();
  895.     wavesRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  896.     wavesRitem->IndexCount = wavesRitem->Geo->DrawArgs["grid"].IndexCount;
  897.     wavesRitem->StartIndexLocation = wavesRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  898.     wavesRitem->BaseVertexLocation = wavesRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  899.  
  900.     mWavesRitem = wavesRitem.get();
  901.  
  902.     mRitemLayer[(int)RenderLayer::Opaque].push_back(wavesRitem.get());
  903.  
  904.     auto gridRitem = std::make_unique<RenderItem>();
  905.     gridRitem->World = MathHelper::Identity4x4();
  906.     XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(5.0f, 5.0f, 1.0f));
  907.     gridRitem->ObjCBIndex = 1;
  908.     gridRitem->Mat = mMaterials["grass"].get();
  909.     gridRitem->Geo = mGeometries["landGeo"].get();
  910.     gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  911.     gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
  912.     gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  913.     gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  914.  
  915.     mRitemLayer[(int)RenderLayer::Opaque].push_back(gridRitem.get());
  916.  
  917.     auto boxRitem = std::make_unique<RenderItem>();
  918.     XMStoreFloat4x4(&boxRitem->World, XMMatrixTranslation(3.0f, 2.0f, -9.0f));
  919.     boxRitem->ObjCBIndex = 2;
  920.     boxRitem->Mat = mMaterials["wirefence"].get();
  921.     boxRitem->Geo = mGeometries["boxGeo"].get();
  922.     boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  923.     boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
  924.     boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
  925.     boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
  926.  
  927.     mRitemLayer[(int)RenderLayer::Opaque].push_back(boxRitem.get());
  928.  
  929.     mAllRitems.push_back(std::move(wavesRitem));
  930.     mAllRitems.push_back(std::move(gridRitem));
  931.     mAllRitems.push_back(std::move(boxRitem));
  932. }
  933.  
  934. void TexWavesApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
  935. {
  936.     UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  937.     UINT matCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(MaterialConstants));
  938.  
  939.     auto objectCB = mCurrFrameResource->ObjectCB->Resource();
  940.     auto matCB = mCurrFrameResource->MaterialCB->Resource();
  941.  
  942.     // For each render item...
  943.     for(size_t i = 0; i < ritems.size(); ++i)
  944.     {
  945.         auto ri = ritems[i];
  946.  
  947.         cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
  948.         cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
  949.         cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
  950.  
  951.         CD3DX12_GPU_DESCRIPTOR_HANDLE tex(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  952.         tex.Offset(ri->Mat->DiffuseSrvHeapIndex, mCbvSrvDescriptorSize);
  953.  
  954.         D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
  955.         D3D12_GPU_VIRTUAL_ADDRESS matCBAddress = matCB->GetGPUVirtualAddress() + ri->Mat->MatCBIndex*matCBByteSize;
  956.  
  957.         cmdList->SetGraphicsRootDescriptorTable(0, tex);
  958.         cmdList->SetGraphicsRootConstantBufferView(1, objCBAddress);
  959.         cmdList->SetGraphicsRootConstantBufferView(3, matCBAddress);
  960.  
  961.         cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
  962.     }
  963. }
  964.  
  965. std::array<const CD3DX12_STATIC_SAMPLER_DESC, 6> TexWavesApp::GetStaticSamplers()
  966. {
  967.     // Applications usually only need a handful of samplers.  So just define them all up front
  968.     // and keep them available as part of the root signature.  
  969.  
  970.     const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
  971.         0, // shaderRegister
  972.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  973.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  974.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  975.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  976.  
  977.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  978.         1, // shaderRegister
  979.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  980.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  981.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  982.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  983.  
  984.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  985.         2, // shaderRegister
  986.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  987.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  988.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  989.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  990.  
  991.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  992.         3, // shaderRegister
  993.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  994.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  995.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  996.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  997.  
  998.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
  999.         4, // shaderRegister
  1000.         D3D12_FILTER_ANISOTROPIC, // filter
  1001.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1002.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1003.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
  1004.         0.0f,                             // mipLODBias
  1005.         8);                               // maxAnisotropy
  1006.  
  1007.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
  1008.         5, // shaderRegister
  1009.         D3D12_FILTER_ANISOTROPIC, // filter
  1010.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1011.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1012.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
  1013.         0.0f,                              // mipLODBias
  1014.         8);                                // maxAnisotropy
  1015.  
  1016.     return { 
  1017.         pointWrap, pointClamp,
  1018.         linearWrap, linearClamp, 
  1019.         anisotropicWrap, anisotropicClamp };
  1020. }
  1021.  
  1022. float TexWavesApp::GetHillsHeight(float x, float z)const
  1023. {
  1024.     return 0.3f*(z*sinf(0.1f*x) + x*cosf(0.1f*z));
  1025. }
  1026.  
  1027. XMFLOAT3 TexWavesApp::GetHillsNormal(float x, float z)const
  1028. {
  1029.     // n = (-df/dx, 1, -df/dz)
  1030.     XMFLOAT3 n(
  1031.         -0.03f*z*cosf(0.1f*x) - 0.3f*cosf(0.1f*z),
  1032.         1.0f,
  1033.         -0.3f*sinf(0.1f*x) + 0.03f*x*sinf(0.1f*z));
  1034.  
  1035.     XMVECTOR unitNormal = XMVector3Normalize(XMLoadFloat3(&n));
  1036.     XMStoreFloat3(&n, unitNormal);
  1037.  
  1038.     return n;
  1039. }
  1040.